GIT

Die Übersichtlichkeit der Seite wird durch Javascript erhöht. Ist dies aktiviert, werden die Texte unter den Überschriften durch Anklicken der Überschriften ein- und ausgeblendet.

Was ist GIT

Git ist ein Versionskontrollsystem Dabei wird immer mit vollständigen lokalen Kopien gearbeitet, die bei Bedarf von einem REMOTE-Ordner heruntergeladen oder hochgeladen werden.

nach oben

Funktionsweise

Das Projektverzeichnis ist das Arbeitsverzeichnis. Es enthält einen Unterordner .git. In diesem Unterordner befindet sich die eigentliche Datenbasis, das Repository. Im Projektverzeichnis werden ansonsten ausschließlich die Dateien gelistet, an denen man gerade arbeitet - man spricht hier allgemein vom Arbeitsverzeichnis . Dies können von git gesteuert in underschiedlichen Entwiklungszweigen, sogenannten Branches, unterschiedliche Dateien sein. Des weiteren wird im Repository eine sogenannte Staging Area verwaltet. Das ist eine Datei innerhalb des .git-Verzeichnisses, die alle Informationen darüber enthält, was man expliziet für einen sogenannten neuen Commit ausgewählt hat, wobei ein Commit einfach nur die Aufnahme von Änderungen im in das aktuelle Repository bedeuted.

Dateien können 3 verschiedene Zustände haben:

committed
Dateien sind genau so im Repository, wie sie im Arbeitsverzeichnis angezeigt werden.
modified
Dateien wurden geändert, wurden aber in dieser geänderten Form noch nicht in das Repository übertragen.
staged
Eine geänderte Datei ist markiert, um Sie in der aktuellen Version in den nächsten Commit-Snapshot zu übernehmen, und so in das Repository zu übertragen.

Grundlegender Workflow

  1. Dateien im Arbeitsverzeichnis werden bearbeitet.
  2. Bearbeitete Dateien werden in die Stating Area aufgenommen, wenn man eine Änderung in einer Datei als abgeschlossen betrachtet und meint, das diese so bei der nächsten Übertragung / Commit als Schnapschuss gespeichert werden soll.
  3. Man macht einen Commit, der die Dateien der Staging Area als Schapschuss permanent im .git-Verzeichnis speichert.

Status von Dateien

Somit gilt, wenn eine Version einer Datei im .git-Verzeichnis gespeichert ist, dann ist diese committet , wenn die Datei geändert und der Staging-Area hinzugefügt wurde, dann ist diese staged und wenn Sie geändert aber nicht der Steaging-Area hinzugefügt wurde, ist sie modified .

nach oben

Befehle

GIT Setup

Setup-Files

/etc/gitconfig
wird angesprochen durch die Option --system
~/.gitconfig oder ~/.config/git/config
wird angesprochen durch die Option --global
  • config-Datei im Repository (.git/config)

Dabei steigt die Priorität von System über Global bis zum Projekt, dass heißt, die Projektkonfiguration übersteuert alle anderen.

nach oben

Setup-Befehle

git-config --global user.name "John Doe" 
git config --global user.email johndoe@example.com
git config --global core.editor emacs
git config --list
Listet alle Einstellungen auf
git config <key>
Zeigt die Einstellung des speziellen Keys

nach oben

Start der Verionskontrolle

Github und die Einbindung eines bestehenden lokalen Projektes

Standard: zunächst lokal versioniert

  • Erstellung des Projektordners
  • init git
  • Nutzung von git local:
    • git add
    • git rm
    • git reset
    • git mv
    • git commit
    • git log
    • git diff
    • git status
    • git branch
    • git checkout
    • git merge
  • Entscheidung zur Veröffentlichung auf Github:
    • mk-github-projekt kopiert aus einem Template-Ordner die GPL-V3-Lizenz, die README.md-Datei und die .gitignore in den aktuellen Ordner
    • README.md und ggf. die .gitignore anpassen
    • git add .
    • git commit -m 'Upload to Github'
    • Anlegen eines leeren Repositories auf Github und kopieren der URL, die unter 'Quick setup' zu finden ist.
    • git remote add hub URL
    • git push -u hub master
  • git wird dann local normal weiter genutzt
  • git push für weitere Uploads

nach oben

wenn noch nicht versioniert

git init

Auf Github ein Repository anlegen und die Adresse kopieren. Diese ist unter dem Button 'Clone or download' zu finden.

Beispiel mit der Adresse: https://github.com/easymf74/Test.git

$ git remote add hub https://github.com/easymf74/Test.git
$ git pull hub master
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Entpacke Objekte: 100% (4/4), Fertig.
Von https://github.com/easymf74/Test
 * branch            master     -> FETCH_HEAD
 * [neuer Branch]    master     -> hub/master
$ echo '.gitignore' >> .gitignore
$ echo '*~' >> .gitignore
$ echo '.[o]' >> .gitignore 
$ git add .
$ git commit -m "Initial Commit"
[master 8c3a1dd] Initial Commit
 1 file changed, 3 insertions(+)
 create mode 100644 wichtig
$ git push -u hub master
Username for 'https://github.com': easymf74
Password for 'https://easymf74@github.com': 
Zähle Objekte: 3, Fertig.
Delta compression using up to 2 threads.
Komprimiere Objekte: 100% (3/3), Fertig.
Schreibe Objekte: 100% (3/3), 340 bytes | 0 bytes/s, Fertig.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/easymf74/Test.git
   cd33ab8..8c3a1dd  master -> master
Branch master konfiguriert zum Folgen von Remote-Branch master von hub.
$ git status
Auf Branch master
Ihr Branch ist auf dem selben Stand wie 'hub/master'.
nichts zu committen, Arbeitsverzeichnis unverändert

nach oben

Einrichtung eines localen Repositorys

Einfach im Projektordner folgenden Befehl absetzen:

git init

Alle eventuell zuvor vorhandenen Unterordner und Dateien sind nicht im Tracking der Versionskontrolle, solange wir sie nicht expliziet hinzufügen und initial comitten:

git add *.cpp
git add *.h
git add LICENSE

git commit -m 'initial project version'

nach oben

Klonen eines Remote-Verzeichnisses

git clon [URL] [ggf. NameZielverzeichnis]

nach oben

Arbeiten mit der Versionscontrolle

Befehlsübersicht

git status
zeigt den Status der Versionskontrolle
git status -s
Status in Kurzschreibweise
git diff
zeigt die Änderungen, die nicht gestaged sind
git diff --staged
zeigt Änderungen in der Staging Area (statt --staged kann man auch --cached schreiben)
git add
fügt eine Datei oder ein Verzeichnis rekursiv in die Stagin Area
git branch
Listet die Aktuellen Branches
git branch -v
zeigt den letzten Commit aller Branches
git branch <neuerBranch>
erzeugt einen neuen Branch
git branch -d <zuLöschenderBranch>
löscht einen Branch
git reset HEAD Dateiname
entfernt eine Datei wieder aus der Stagin Area
git checkout <Branch>
wechselt in den Branch
git checkout - b <Branch>
erzeugt einen neuen Branch und wechselt hinein
git checkout -- Datei
Setzt die Änderungen an einer Datei im Arbeitsverzeichnis auf den letzten Schnapschuß zurück. ACHTUNG: Alle Änderungen, die seit dem letzten Schnapschuß gemacht wurden sind unwiederruflich verloren!!!
git commit
startet den voreingestellten Editor mit dem Status als Kommentar, in dem man einen Text für den Commit erstellen kann. Nach beenden des Editors, wird die Commit mit der Nachricht erstellt
git commit -v
wie git commit mit Diff satt Status im Kommentar
git commit -m "Nachricht"
Erstellt den Commit direkt mit der angegebenen Nachricht, ohne einen Editor zu öffnen.
git commit -a
Alle getrackten Dateien werden direkt ohne Staging Area comitted, dass heißt sie brauchen nicht mit git add hinzugefügt werden.
git commit --amend
letzten Commit, wieder in die Stagig Area holen, um Änderungen vorzunehmen, die den vorherigen Commit überschreiben.
git merge <Branch>
überführt den genannten Branch in den aktuellen
git rm
beendet das Tracking für eine Datei und löscht diese aus dem Arbeitsverzeichnis.
git rm -f
Löschen auch wenn bereits Änderungen gestaged sind
git rm --cached
beendet das Tracking ohne die Datei im Arbeitsverzeichnis zu löschen.
git mv alt neu
Benennt eine Datei von alt in neu um
git log
Zeigt die Historie (Das Changelog) in umgedrehter chronologischer Reihenfolge
git log -p
Zeigt das log mit den Diffs
git log -[N]
N=2 zeigt die letzten beiden commits
git log --stat
gibt unter jedem commit die Liste und die Anzahl der geänderten Dateien und die Anzahl der neuen und gelöschten Zeilen in diesen Dateien aus.
git log -Sstring
zeigt nur Commits die eine Änderung haben die diesen String hinzufügt oder löscht

nach oben

Einige Befehle im Detail

git status -s

Status in komprimierter Form. Dabei wird vor der datei oder dem Verzeichnis ein 2-spaltiger Stausindikator angezeigt.

Linke Spalte
Status der Staging Area
Rechte Spalte
Status des Arbeitsverzeichnisses
??
Dateien die nicht getrackt sind
M
geändert aber nicht gestaged
M
geändert und gestaged
MM
geändert und gestaged, dann wieder geändert
A_
neue Datei gestaged

nach oben

git log

-p
Zeigt das Log mit den Diffs
--stat
Zeigt die Änderungsstatistik für jeden Commit
--shortstat
Zeigt nur die geändert/hinzugefügt/gelöscht-Zeile des --stat-Kommandos
--name-only
Zeigt die Liste der geänderten Dateien nach den Commit-Informationen
--name-status
zeigt die Liste der Dateien mit hinzugefügt/geändert/gelöscht-Informationen
--abbrev-commit
zeigt die Checksumme gekürzt
--relative-date
Zeigt an wie lange der Commit her ist
--graph
zeigt einen ASCII-Graphen mit den Branch-Infos an
--pretty
Zeigt die Committs in einem konfigurierbaren Format
--since=N.weeks
N=2 zeigt das Log für die letzten 2 Wochen

git log --pretty=

Der Befehl ändert die Ausgabe der Log-Datei

oneline
gibt jeden Commit in einer einzigen Zeile aus
short, full, fuller
mehr oder weniger Infos
format
lässt das Ausgabeformat anpassen

git log -- pretty=format:"..."

Für ... können folgende Formatoptionen angegeben werden

%H
Commit Hash
%h
abgekürzter Commit Hash
%T
Baum Hash
%t
Baum Hash gekürzt
%P
Eltern Hasches
%p
Eltern Hasches abgekürzt
%an
Name des Autors
%ae
Mail des Autors
%ad
Autor Datum (Format berücksichtigt die --date=option)
%ar
Autor Datum relativ
%cn
Name des Committers
%ce
Mail des Committers
%cd
Datum des Committers
%cr
Datum des Committers relativ
%s
Subjekt

Beispiel:

git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 Years ago : changed the version
number

git log --pretty format:"..." --graph

gibt einen ASCII-Graphen aus, der die Branch- und Merge- Historie anzeigt.

nach oben

log filtern

git log --since=

(oder statt --since, was für seit steht geht auch --until, was für bis steht)

Man kann hier Daten wie folgt spezifizieren:

  • "2008-01-15"
  • "2 years 1 day 3 minutes ago"

nach oben

git log -N

Anzahl der letzten Commits die Angezeigt werden sollen

nach oben

Suche nach bestimmten Commits

--author
nur Commits eines bestimmten Autors anzeigen
--grep
suche nach Schlüsselwörtern in den Commit-Nachrichten
--all-match
wenn mehrere Kriterien angegeben wurden, wird Standardmäßig alles angezeigt, wo nur ein Kriterium zutrifft. Dise Option lässt die Filter in Kombination wirken.
-Sstring
zeigt nur Commits, bei denen der angegebene String hinzugefügt oder gelöscht wurde.
--/pfad
zeigt nur Commits die diese Datei(en) betreffen, wobei die Option immer die letzte sein muss um den Pfad von den Optionen zu trennen
--since, --after
Commits nach einem bestimmten Datum
--until, --before
Commits bevor einem bestimmten Datum
--committer
Commits eines bestimmten Committers

Beispiel:

git log --pretty="%h - %s" --author=gitster --since="2008-10-01" \
   --before="2008-11-01" --no-merges -- t/

nach oben

Besonderheiten

Dateien ausschließen

Manche Dateien möchte man generell von der Versionskontrolle ausschließen. Dies macht zum Beispiel bei für das kompilierte Programm Sinn oder ggf Log-Dateien oder Backups. Solche Dateien kann man in einer Datei .gitignore auflisten. Beispiele:

*.[oa]
Alle Dateien, die mit .o oder .a enden, werden ignoriert
lib.a
tracke lib.a-Dateien auch, wenn .a-Dateien ignoriert werden
*~
ignoriert Dateien, die mit einer Tilde enden
/TODO
ignoriere TODO-Dateien im aktuellen Verzeichnis, nicht aber in Unterverzeichnissen
build/
Ignoriere alle dateien im Ordner build/
doc/*.txt
ignoriert doc/notes.txt aber nicht doc/server/arch.txt
doc/**/*.pdf
ignoriert alle .pdf-Datein unter doc/

Folgende Regeln gelten für die Angaben in der Ignore-Datei:

  • Leerzeilen oder Zeilen, die mit # (Raute) beginnen, werden ignoriert
  • Die normalen Muster funktionieren
  • ein vorangestelltes Slash (/), für rekursive Anwendung vermeiden
  • ein abschließendes Slash spezifiziert ein Verzeichnis
  • ein vorangestelltes Ausrufezeichen (!) negiert das Muster

Beispiele für Muster:

*
0 - beliebig viele beliebige Zeichen
[abc]
alle Zeichen in der Klammer sind gültig
?
steht für ein einzelnes belibiges Zeichen
[0-9]
alle Zeichen von bis sind gültig

nach oben

Aliases

Für die Git-befehle lassen sich leicht Aliasnamen definieren, die die Eingabe der Befehle in der Zukunft verkürzen

git config --global alias.<kürzel> <Befehl>
git config --global alias.co chackout
git checkout entspricht danach git co

So lassen sich auch neue Befehle definieren:

git config --global alias.unstage 'reset HEAD --'

Damit kann statt:

git reset HEAD -- fileA

einfach geschrieben werden:

git unstage fileA

oder ein last -Kommando:

git config --global alias.last 'log -1 HEAD'
ermöglicht:
git last

nach oben

Zwischenspeichern, Bug fixen

Wenn man bereits an neuen Funktionen arbeitet, die allerdings noch nicht fertig gestellt sind, so dass man diese committen wollen würde, aber mann ggf. zunächst andere Änderungen, wie beispielsweise Bugfix an den bisherigen Code vornehmen möchte, so kann mann die derzeitige Arbeit zwischenspeichern, die Änderungen vornehmen und dann die zwischengespeicherte Arbeit wieder hervorholen, ohne dafür extra Branches anzulegen und halbfertige Arbeiten zu comitten. Dazu geht man wie folgt vor.

zwischenspeichern der bisherigen unvollständigen Arbeit

git stash

Danach hat man zunächst wieder den Stand vom letzten commit und kann die Änderungen daran vornehmen.

nach oben

zum weiterarbeiten an der zwischengespeicherten Arbeit

git stash pop

nach oben

Etwas vergessen

Eine Datei kan man zum letzten Schnapschuß wie folgt ergänzen:

git commit -m 'Ich denke, ich habe alles'
git add vergesseneDatei
git add --amend

Dabei wird der letzte Schnapschuß überschrieben.

nach oben

Branches

Ein Branch ist ein Pointer auf einen Versionsstand Der Pointer HEAD zeigt immer auf den aktuellen Branch

git branch <neuerBranch>
erzeugt einen neuen branch (Zweig) zum aktuellen Commit
git branch
listet alle Branches
git branch -v
zeigt die letzten vommits aller Branches
git branch --merged
Zeigt die Branches die bereits in den aktuellen überführt wurden
git branch --no-merged
zeigt die Branches die noch nicht in den aktuellen Zweig überführt worden sind
git branch -d <branch>
löscht einen Branch

nach oben

Remotes

git clone <URL>
Klont von der URL und fügt diese als Kurzname origin zu den Remotes hinzu
git remote add <shortname> <URL>
Fügt einen neuen Remote mit der angegebenen URL mit dem angegebenen shortname als Namen ein, so dass nun der Kurzname an Stelle der URL genutzt werden kann
git remote rename <alt> <neu>
ändert den Remotekurznamen
git remote rm <remote>
entfernt einen Remote
git remote
Listet den Kurznamen aller Remotes auf, die spezifiziert sind
git remote -v
zeigt zusätzlich die URL an
git remote show <remote-name>
zeigt detaillierte Informationen zum Remote
git ls-remote <remotename>
Liste der Remotereferrenzen
git fetch <remote-name>
Aktuallisiert vom Remote
git fetch origin
Aktuallisiert ein geklontes Repository von der URL von der dieses geklont wurde
git checkout -b serverfix origin/serverfix
erstellt einen Branch serverfix der auf einen heruntergeladenen (fetch) remote-tracking-branch origin/serverfix basiert
git checkout --track origin/serverfix
trackt einen anderen Remoteranche als den Standard master. Hier serverfix!
git pull
aktuallisiert von remote und führt diesen local mit den eigenen Änderungen zusammen, wenn das Tracking des Remote-Branches eingestellt ist. Dies wird durch git clone automatisch eingestellt.
git push [remote-name] [branch-name]
lädt alle lokalen Änderungen in den branch des Remote
git push origin master
Änderungen von einen Klone hochladen, sofern für den Server, von dem geklont wurde, Schreibrechte bestehen und niemand anderes in der zwischenzeit Änderungen hochgeladen hat. Wurde bereits durch jemand anderen Änderungen vorgenommen, so sind diese zunächst local zu intigrieren, bevor sich die eigenen Änderungen hochladen lassen.
git push origin localbranch:remotebranch
lädt den localen Branch localbranch als remotebranch auf den Server
git push origin --delete serverfix
Löscht den Pointer auf den Branch serverfix auf dem Server

Github

Auf github einfach ein Repository anlegen, ohne jedliche Einstellungen. Dann im localen Projektordner Github wie folgt bekannt machen und den aktuellen Stand hochladen. (Hierzu wird benutzername und Passwort benötigt)

git remote add hub https://github.com/easymf74/[REPOSITORY_NAME]
git push -u hub master

nach oben

Taggen

Wichtige Stände können getaggt, also markiert werden. Es gibt zwei unterschiedliche Arten von Tags

leichtgewichtige Tags
Links zu einem bestimmten Commit
kommentierte Tags
eigenständige Objekte in der Database mit:
  • Checksumme
  • Name des Taggers
  • Mail des Taggers
  • Datum des Taggens
  • Signatur (GPG)

Befehle

git tag -a <tagname> -m "Nachricht"
erstellt einen kommentierten Tag
git tag -a <tagname> <[Teil einer] Commit-Checksumme>
setzt den Tag für den Commit dessen Checksumme, der angegebenen entspricht
git tag <tagname>
erstellt einen leichtgewichtigen Tag
git tag
listet ale Tags alphabetisch auf
git tag -l "Suchmuster"
Listet alle Tags auf, die dem Suchmuster entsprechen
git show <tagname>
zeigt Informationen zum bestimmten Tag an
git push origin <tagname>
überträgt den Tag zum Remote origin, Tags müssen expliziet übertragen werden
git push origin --tags
überträgt alle Tags zum remote origin
git checkout -b [branchname] [tagname]
erstellt einen neuen Branch auf der Grundlage des bestimmten Tags

nach oben